package loader

import (
	"context"
	"fmt"
	"time"

	"github.com/smart-snapshotter/pkg/cache"
	"github.com/smart-snapshotter/pkg/types"
)

// EnhancedSmartLoader extends the basic SmartLoader with advanced cache management
type EnhancedSmartLoader struct {
	*SmartLoader
	prefetchManager    *cache.PrefetchManager
	consistencyManager *cache.ConsistencyManager
	cacheConfig        cache.Config
}

// NewEnhancedSmartLoader creates a new enhanced smart loader with advanced cache management
func NewEnhancedSmartLoader(config types.LoaderConfig, storage types.StorageBackend, cacheConfig cache.Config) (*EnhancedSmartLoader, error) {
	// Create the base cache
	baseCache, err := cache.New(cacheConfig)
	if err != nil {
		return nil, fmt.Errorf("failed to create cache: %w", err)
	}

	// Wrap with adapter to match types.Cache interface
	adaptedCache := cache.NewCacheAdapter(baseCache)

	// Create base smart loader
	baseLoader, err := NewSmartLoader(config, storage, adaptedCache)
	if err != nil {
		return nil, fmt.Errorf("failed to create smart loader: %w", err)
	}

	// Create prefetch manager
	prefetchConfig := cache.PrefetchConfig{
		Enabled:          config.PrefetchEnabled,
		MaxWorkers:       config.MaxConcurrency,
		BatchSize:        100,
		PriorityStrategy: "priority",
		Timeout:          30 * time.Second,
		RetryAttempts:    3,
		RetryDelay:       1 * time.Second,
	}

	prefetchManager, err := cache.NewPrefetchManager(baseCache, prefetchConfig)
	if err != nil {
		return nil, fmt.Errorf("failed to create prefetch manager: %w", err)
	}

	// Create consistency manager
	consistencyConfig := cache.ConsistencyConfig{
		Enabled:           true,
		CheckInterval:     5 * time.Minute,
		ChecksumAlgorithm: "sha256",
		AutoRepair:        true,
		ValidationMode:    "relaxed",
		MaxAge:            24 * time.Hour,
		CleanupInterval:   1 * time.Hour,
	}

	consistencyManager, err := cache.NewConsistencyManager(baseCache, consistencyConfig)
	if err != nil {
		return nil, fmt.Errorf("failed to create consistency manager: %w", err)
	}

	return &EnhancedSmartLoader{
		SmartLoader:        baseLoader,
		prefetchManager:    prefetchManager,
		consistencyManager: consistencyManager,
		cacheConfig:        cacheConfig,
	}, nil
}

// LoadWithCache loads data with enhanced cache management
func (esl *EnhancedSmartLoader) LoadWithCache(ctx context.Context, key string, cacheTTL time.Duration) ([]byte, error) {
	// Validate cache entry if consistency checking is enabled
	if esl.consistencyManager != nil {
		result, err := esl.consistencyManager.ValidateEntry(ctx, key)
		if err == nil && !result.Valid && result.Action == "repaired" {
			// Entry was repaired, reload from storage
			return esl.loadFromStorage(ctx, key, cacheTTL)
		}
	}

	// Try to load from cache first
	data, err := esl.SmartLoader.Load(ctx, key)
	if err == nil {
		return data, nil
	}

	// Load from storage and cache it
	return esl.loadFromStorage(ctx, key, cacheTTL)
}

// loadFromStorage loads data from storage and caches it
func (esl *EnhancedSmartLoader) loadFromStorage(ctx context.Context, key string, cacheTTL time.Duration) ([]byte, error) {
	// Load from storage
	data, err := esl.storage.LoadFile(ctx, key)
	if err != nil {
		return nil, fmt.Errorf("failed to load from storage: %w", err)
	}

	// Cache the data with specified TTL
	if err := esl.cache.Set(ctx, key, data, cacheTTL); err != nil {
		// Log warning but don't fail the operation
		fmt.Printf("Warning: failed to cache data for key %s: %v\n", key, err)
	}

	// Update consistency checksum if enabled
	if esl.consistencyManager != nil {
		if err := esl.consistencyManager.UpdateChecksum(ctx, key); err != nil {
			fmt.Printf("Warning: failed to update checksum for key %s: %v\n", key, err)
		}
	}

	return data, nil
}

// PrefetchKeys prefetches multiple keys with intelligent batching
func (esl *EnhancedSmartLoader) PrefetchKeys(ctx context.Context, keys []string, priority float64) (string, error) {
	if esl.prefetchManager == nil {
		return "", fmt.Errorf("prefetch manager not available")
	}

	return esl.prefetchManager.PrefetchKeys(ctx, keys, priority)
}

// WarmCache warms the cache with frequently accessed keys
func (esl *EnhancedSmartLoader) WarmCache(ctx context.Context, keys []string) error {
	if esl.prefetchManager == nil {
		return fmt.Errorf("prefetch manager not available")
	}

	return esl.prefetchManager.WarmCache(ctx, keys)
}

// GetCacheStats returns detailed cache statistics
func (esl *EnhancedSmartLoader) GetCacheStats(ctx context.Context) (map[string]interface{}, error) {
	stats := make(map[string]interface{})

	// Get basic cache stats
	cacheStats, err := esl.cache.GetStats(ctx)
	if err != nil {
		return nil, fmt.Errorf("failed to get cache stats: %w", err)
	}
	stats["cache"] = cacheStats

	// Get loader stats
	loaderStats, err := esl.SmartLoader.GetStats(ctx)
	if err != nil {
		return nil, fmt.Errorf("failed to get loader stats: %w", err)
	}
	stats["loader"] = loaderStats

	// Get prefetch stats if available
	if esl.prefetchManager != nil {
		prefetchStats := esl.prefetchManager.GetStats()
		stats["prefetch"] = prefetchStats
	}

	// Get consistency stats if available
	if esl.consistencyManager != nil {
		consistencyStats := esl.consistencyManager.GetStats()
		stats["consistency"] = consistencyStats
	}

	// Get tier stats if using hybrid cache
	if adapter, ok := esl.cache.(*cache.CacheAdapter); ok {
		if hybridCache, ok := adapter.Cache.(*cache.HybridCache); ok {
			tierStats := hybridCache.GetTierStats()
			stats["tiers"] = tierStats
		}
	}

	return stats, nil
}

// GetConsistencyReport returns cache consistency report
func (esl *EnhancedSmartLoader) GetConsistencyReport() (map[string]interface{}, error) {
	if esl.consistencyManager == nil {
		return nil, fmt.Errorf("consistency manager not available")
	}

	return esl.consistencyManager.GetConsistencyReport(), nil
}

// ValidateCacheEntry validates a specific cache entry
func (esl *EnhancedSmartLoader) ValidateCacheEntry(ctx context.Context, key string) (*cache.ConsistencyResult, error) {
	if esl.consistencyManager == nil {
		return nil, fmt.Errorf("consistency manager not available")
	}

	return esl.consistencyManager.ValidateEntry(ctx, key)
}

// InvalidateCacheEntry invalidates a specific cache entry
func (esl *EnhancedSmartLoader) InvalidateCacheEntry(key string) error {
	if esl.consistencyManager == nil {
		return fmt.Errorf("consistency manager not available")
	}

	// Invalidate in consistency manager
	if err := esl.consistencyManager.InvalidateEntry(key); err != nil {
		return fmt.Errorf("failed to invalidate in consistency manager: %w", err)
	}

	// Delete from cache
	return esl.cache.Delete(context.Background(), key)
}

// ClearCache clears all cache entries
func (esl *EnhancedSmartLoader) ClearCache(ctx context.Context) error {
	// Clear consistency manager
	if esl.consistencyManager != nil {
		if err := esl.consistencyManager.InvalidateAll(); err != nil {
			return fmt.Errorf("failed to invalidate consistency manager: %w", err)
		}
	}

	// Clear cache
	return esl.cache.Clear(ctx)
}

// AnalyzeAccessPattern analyzes access patterns for intelligent prefetching
func (esl *EnhancedSmartLoader) AnalyzeAccessPattern(recentKeys []string) []string {
	if esl.prefetchManager == nil {
		return []string{}
	}

	return esl.prefetchManager.AnalyzeAccessPattern(recentKeys)
}

// GetPrefetchJobStatus returns the status of a prefetch job
func (esl *EnhancedSmartLoader) GetPrefetchJobStatus(jobID string) (*cache.PrefetchJob, error) {
	if esl.prefetchManager == nil {
		return nil, fmt.Errorf("prefetch manager not available")
	}

	return esl.prefetchManager.GetJobStatus(jobID)
}

// Stop stops the enhanced smart loader
func (esl *EnhancedSmartLoader) Stop() error {
	var errs []error

	// Stop base loader
	if err := esl.SmartLoader.Stop(); err != nil {
		errs = append(errs, fmt.Errorf("failed to stop base loader: %w", err))
	}

	// Stop prefetch manager
	if esl.prefetchManager != nil {
		if err := esl.prefetchManager.Stop(); err != nil {
			errs = append(errs, fmt.Errorf("failed to stop prefetch manager: %w", err))
		}
	}

	// Stop consistency manager
	if esl.consistencyManager != nil {
		if err := esl.consistencyManager.Stop(); err != nil {
			errs = append(errs, fmt.Errorf("failed to stop consistency manager: %w", err))
		}
	}

	if len(errs) > 0 {
		return fmt.Errorf("errors stopping enhanced loader: %v", errs)
	}

	return nil
}

// ConfigureCache configures the cache with new settings
func (esl *EnhancedSmartLoader) ConfigureCache(config cache.Config) error {
	// Create new cache
	newCache, err := cache.New(config)
	if err != nil {
		return fmt.Errorf("failed to create new cache: %w", err)
	}

	// Update cache reference
	esl.cache = cache.NewCacheAdapter(newCache)
	esl.cacheConfig = config

	// Update consistency manager if exists
	if esl.consistencyManager != nil {
		if err := esl.consistencyManager.Stop(); err != nil {
			return fmt.Errorf("failed to stop old consistency manager: %w", err)
		}

		consistencyConfig := cache.ConsistencyConfig{
			Enabled:           true,
			CheckInterval:     5 * time.Minute,
			ChecksumAlgorithm: "sha256",
			AutoRepair:        true,
			ValidationMode:    "relaxed",
			MaxAge:            24 * time.Hour,
			CleanupInterval:   1 * time.Hour,
		}

		esl.consistencyManager, err = cache.NewConsistencyManager(newCache, consistencyConfig)
		if err != nil {
			return fmt.Errorf("failed to create new consistency manager: %w", err)
		}
	}

	// Update prefetch manager if exists
	if esl.prefetchManager != nil {
		if err := esl.prefetchManager.Stop(); err != nil {
			return fmt.Errorf("failed to stop old prefetch manager: %w", err)
		}

		prefetchConfig := cache.PrefetchConfig{
			Enabled:          esl.config.PrefetchEnabled,
			MaxWorkers:       esl.config.MaxConcurrency,
			BatchSize:        100,
			PriorityStrategy: "priority",
			Timeout:          30 * time.Second,
			RetryAttempts:    3,
			RetryDelay:       1 * time.Second,
		}

		esl.prefetchManager, err = cache.NewPrefetchManager(newCache, prefetchConfig)
		if err != nil {
			return fmt.Errorf("failed to create new prefetch manager: %w", err)
		}
	}

	return nil
}